<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    .box {
        position: absolute;
    }
</style>

<body>
    <script>
        //  对象 ： 方块   食物    蛇    地图 

        //  地图  

        // 定义一个地图类 需要生成一个地图 
        //地图： div  线框   宽  高   在body里面
        class Domain {
            constructor() {
                this.ele = document.createElement("div");
                //调用自己设置样式的方法
                this.setStyle();
            }
            setStyle() {
                //线框   宽  高  相对路径  自动居中  在body里面
                //this.ele :就是上面创建的div
                this.ele.style.width = '600px'
                this.ele.style.height = '600px'
                this.ele.style.position = "relative"
                this.ele.style.border = '1px solid'
                this.ele.style.margin = '0 auto'

                //添加到body里面
                document.body.appendChild(this.ele);
            }
        }

        var map = new Domain();

        //方块
        class Rect {
            //快的left top    背景颜色
            constructor(x, y, color) {
                this.x = x;
                this.y = y;
                this.color = color;
                //调用设置样式的
                this.setStyle();
            }

            setStyle() {
                this.ele = document.createElement("div");
                //宽高50px 绝对路径 left top距离 背景色
                this.ele.style.width = '50px'
                this.ele.style.height = '50px'
                this.ele.style.left = this.x + "px"
                this.ele.style.top = this.y + "px"
                this.ele.style.border = '1px solid'
                this.ele.style.backgroundColor = this.color;
                this.ele.style.position = 'absolute'

                //添加到地图中  map.ele:地图div框
                //往地图的div里面添加方块div
                map.ele.appendChild(this.ele);
            }
        }

     

        //吃食物（就是方块）  有要求（随机出现在不同的位置）
        class Food{

            constructor(){
               //Rect对象里面有把块添加到地图div中的代码
               this.rect = new Rect(parseInt(Math.random()*12)*50,parseInt(Math.random()*12)*50,"green")
            }

        }
        //创建食物
        let food = new Food();


        // let r1 = new Rect(0,0,'blue')
        // let r2 = new Rect(50,0,'blue')
        // let r3 = new Rect(100,0,'red')

        //蛇：是由多个方块组成一条蛇  方块对象  蛇：方块数组
        class Snake {
            constructor() {
                //方向属性
                this.dir = "right";

                //这里面装方块，组成蛇 
                this.bodyArr = [];
                //创建蛇的身体
                this.createSnakeBody()
                //蛇移动
                this.move();
            }
            createSnakeBody() {
                for (let i = 0; i < 3; i++) {
                    //组装蛇身体   三目
                    this.bodyArr.push(new Rect(i * 50, 0, (i == 2 ? "red" : "blue")))
                }
            }
            //碰撞  蛇头      食物
            isCrash(headEle,foodEle){
                //判断重合
                let aX = parseInt(headEle.style.left);
                let aY = parseInt(headEle.style.top);
                
                let bX = parseInt(foodEle.style.left);
                let bY = parseInt(foodEle.style.top);
                //当蛇头的left，top等于食物的left，top  重合
                //认为要长大了
                return aX === bX && aY === bY
            }
            //蛇动起来的方法
            move() {
                setInterval(()=> {
                    //1.蛇头移动 记住蛇头初始的位置，后面添加蛇身体的
                    var head = this.bodyArr[this.bodyArr.length - 1];
                    //console.log(head);
                    var pos = {
                        x: parseInt(head.ele.style.left),
                        y: parseInt(head.ele.style.top)
                    }
                    //console.log(pos);

                    //蛇在运动的过程中吃
                    switch(this.dir){
                        //上下左右移动
                        case "right":{
                            head.ele.style.left = pos.x + 50 + 'px';
                            break;
                        }
                        case "left":{
                            head.ele.style.left = pos.x - 50 + 'px';
                            break;
                        }
                        case "up":{
                            head.ele.style.top = pos.y - 50 + 'px';
                            break;
                        }
                        case "down":{
                            head.ele.style.top = pos.y + 50 + 'px';
                            break;
                        }
                    }

                    //判断蛇头时候和食物进行了重叠
                              // 蛇头div       食物div
                    let isC = this.isCrash(head.ele,food.rect.ele);
                    console.log(isC);
                    //碰撞了？
                    //1.蛇加长（走就在加长） 2.删除食物 3.生产新的食物
                    if(isC){
                        //1.删除食物
                        food.rect.ele.remove();
                        //2.怎么生产新的事物
                        food = new Food();
                    }else{
                    //没碰着？继续按照方向走就行了
                        //1.1蛇头移动
                        //head.ele.style.left = pos.x + 50 + 'px';

                        //2.删除蛇尾， 从内存也要删除对象
                        //这个方法：删除数组中的第一个元素 ，而且返回被删除的元素给你
                        let oneRect = this.bodyArr.shift();
                        oneRect.ele.remove();
                    }

                    //3.在蛇头原来的位置，填充蛇身体  给数组指定的位置添加实例
                    //第二个参数如果是0,就代表我要做添加操作
                    this.bodyArr.splice(this.bodyArr.length - 1, 0, new Rect(pos.x, pos.y, 'blue'))
                }, 500)
            }
        }

        let snake = new Snake();

        //绑定页面的键盘时候
        document.onkeydown = function(e){
            //比如按的是w  key获取到"w"字符串
            let key = e.key

            switch(key){
                case "w":{ //up  前提条件：之前的方法不能是往下的
                    if(snake.dir !== "down"){
                        snake.dir = "up"
                    }
                    break;
                }
                case "a":{ //up  前提条件：之前的方法不能是往下的
                    if(snake.dir !== "right"){
                        snake.dir = "left"
                    }
                    break;
                }
                case "s":{ //up  前提条件：之前的方法不能是往下的
                    if(snake.dir !== "up"){
                        snake.dir = "down"
                    }
                    break;
                }
                case "d":{ //up  前提条件：之前的方法不能是往下的
                    if(snake.dir !== "left"){
                        snake.dir = "right"
                    }
                    break;
                }
            }
        }

    </script>
</body>

</html>